package cn.tellfish.studydemo.demo;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class Curator {


    //我们用一个static的map模拟一个第三方独立缓存
    public static Map<String, Object> redis = new HashMap<>();
    public static final String key = "redisKey";

    public static void main(String[] args) throws InterruptedException {
        //创建俩个对象分别模拟2个进程
        RedisProcess processA = new RedisProcess();
        RedisProcess processB = new RedisProcess();

        //每个进程别分用50个线程并发请求
        ExecutorService service = Executors.newFixedThreadPool(100);
        for (int i = 0; i < 50; i++) {
            service.execute(processA);
            service.execute(processB);
        }

        service.shutdown();
        service.awaitTermination(30, TimeUnit.SECONDS);
    }

    public static class RedisProcess implements Runnable {
        //        CuratorFramework client;
        //ZK分布式锁
        InterProcessMutex distributedLock;
        //JVM内部锁
        ReentrantLock jvmLock;

        public RedisProcess() {
            CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181",
                    new ExponentialBackoffRetry(1000, 3));
            client.start();
            distributedLock = new InterProcessMutex(client, "/mylock");
            jvmLock = new ReentrantLock();
        }


        private Long add() {


            Long val = (Long) redis.get(key);
            if (val == null) {
                val = 0L;
            } else {
                val = val + 1;
            }
            redis.put(key, val);
            return val;

        }

        @Override
        public void run() {

//              //没有锁
//
//            try {
//                Thread.sleep(1000);
//                System.out.println(add());
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }

//            // jvm 锁
//
//            try {
//                Thread.sleep(1000);
//                jvmLock.lock();
//                System.out.println(add());
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            } finally {
//                jvmLock.unlock();
//            }

//            if (1 == 1)
//                return;

            try {

                //这里延时1000毫秒的目的是防止线程过快的更新资源，那么其它线程在步骤(1)处就返回true了.
                Thread.sleep(5000);

                //获取JVM锁(同一进程内有效)
                jvmLock.lock();

                //这里延时500毫秒的目的是防止线程过快更新资源，其它线程在步骤(2)就返回true了。

                try {
                    //获取zk分布式锁
                    distributedLock.acquire();
                    System.out.println("线程:" + Thread.currentThread() );
                    System.out.println(add());

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    //释放ZK锁
                    try {
                        distributedLock.release();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //释放JVM锁
                jvmLock.unlock();
            }

        }
    }


}